package common.helper.json;

import java.util.Map;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.bson.BsonDocument;
import org.bson.BsonInt32;
import org.bson.BsonArray;
import org.bson.BsonString;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;

public class JsonFormatter {
	public static String formatSearchResponse(SearchResponse response){
		return response.toString();
		
		//return formatWithBsonLib(response);
		//return formatWithJsonLib(response);
	}
	
	/*
	 * Using Bson (Mongodb)
	 */
	public static String formatWithBsonLib(SearchResponse response){
		BsonDocument ret_bson = new BsonDocument();
		
		BsonDocument bson = BsonDocument.parse(response.toString());
		
		System.out.println("BSONDocument : \n" + bson.toString());
		
		BsonInt32 _time = bson.getInt32("took");
		ret_bson.append("_time", _time);
		
		BsonDocument hits = bson.getDocument("hits");
		BsonInt32 _total = hits.getInt32("total");
		ret_bson.append("_total", _total);
		
		BsonArray ret_array = new BsonArray();
		
		BsonArray hits_array = hits.getArray("hits");
		int size = hits_array.size();
		for(int i = 0; i < size; i++){
			BsonDocument item = (BsonDocument) hits_array.get(i);
			BsonString _id = item.getString("_id");
			BsonDocument ret_item = item.getDocument("_source");
			ret_item.append("_id", _id);
			
			ret_array.add(ret_item);
		}
		ret_bson.append("_source", ret_array);
		
		System.out.println("RetBSONDocument : \n" + ret_bson.toString());
		
		return ret_bson.toJson();
	}
	/*
	 * Using Jackson
	 */
	public static String formatWithJackson(SearchResponse response){
		
		return "";
	}
	
	
	/*
	 * Using Gson-Lib
	 */
	public static String formatWithGsonLib(SearchResponse response){
		
		return "";
	}
	
	
	/*
	 * Using Json-Lib
	 */
	public static String formatWithJsonLib(SearchResponse response){
		JSONObject ret_json = new JSONObject();
		/*
		 * 将json字符串转成json对象
		 * 可以进行！！！
		 */
		JSONObject json = JSONObject.fromObject(response.toString());
		//JSONObject json = JSONObject.fromObject(response);
		/*
		 * 出错
		 * 从 "response对象"解析出的 JSON对象 , 与从 "response.toString()字符串"解析出的JSON对象并不一样
		 * 后者少了一些域
		 */
		
		System.out.println("JSONObject : \n" + json.toString());
		
		Long _time = json.getLong("took");
		ret_json.accumulate("_time", _time);
		
		JSONObject hits = json.getJSONObject("hits");
		
		Long _total = hits.getLong("total");
		ret_json.accumulate("_total", _total);
		
		JSONArray ret_array = new JSONArray();
		
		JSONArray hits_array = hits.getJSONArray("hits");
		int size = hits_array.size();
		for(int i = 0; i < size; i++){
			JSONObject item = hits_array.getJSONObject(i);
			
			String _id = item.getString("_id");
			JSONObject ret_item = item.getJSONObject("_source");
			ret_item.accumulate("_id", _id);
			
			ret_array.add(ret_item);
		}
		
		ret_json.accumulate("_source", ret_array);
		
		System.out.println("RetJSONObject : \n" + ret_json.toString());
		
		return ret_json.toString();
	}
	
	/*
	 * Using Json-lib
	 */
	public static String formatWithJsonLibHybrid(SearchResponse response){
		
		SearchHits search_hits = response.getHits();
		Long _time = response.getTookInMillis();
		Long _total = search_hits.getTotalHits();
		/*
		 * using net.sf.json-lib
		 */
		JSONObject json = new JSONObject();
		json.put("_time", _time);
		json.put("_total", _total);
		
		SearchHit[] search_hit_set = search_hits.getHits();
		
		JSONArray array = new JSONArray();
		
		for(int i = 0; i < search_hit_set.length; i++){
			String _id = search_hit_set[i].getId();
			
			Map<String, Object> _source = search_hit_set[i].getSource();
			JSONObject item = JSONObject.fromObject(_source); 
			item.accumulate("_id", _id);
			
			array.add(item);
		}
		json.accumulate("_source", array);
		
		//return response.toString();
		
		return json.toString();
	}

	public static ObjectMapper getOutputObjectMapper(){
		ObjectMapper mapper = new ObjectMapper();
		mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
		mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
		mapper.configure(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, true);
		return mapper;
	}


	
	
}
